#include "OiPCH.hpp"
#include "OiDiffAxis.hpp"

namespace Oi { namespace PLScannerCore {

class DiffAxisImpl
{
public:
    void drawDiffAxis(QPainter* painter, double w, double h);

public:
    DiffAxis::Mode _mode;
    DiffAxis::Type _type;
    double _step;
    double _start;
    double _end;
    int _decimals;
    QList<QString> _descriptions;
};

void DiffAxisImpl::drawDiffAxis(QPainter* painter, double w, double h)
{
    double interval = fabs(_end - _start) / fabs(_step);
    double midValue = ( _end + _start ) / 2;
    if (interval < 1)
    {
        return;
    }

    painter->save();

    painter->setPen(Qt::black);

    double fontH = painter->fontMetrics().height();

    if (_mode == DiffAxis::vertical)
    {
        painter->drawLine(0.5 * w, 0, 0.5 * w , h);
        
        double stepH = h / interval;
        for(int i = -interval; i < interval; i++)
        {
            double tempH = h / 2 + i * stepH;

            //if (tempH >= 0 && tempH < h)
            {
                painter->drawLine(0.5 * w - 7, tempH, 0.5 * w + 7, tempH);

                if (tempH - fontH - 1 < 0 && tempH >= 0)
                {
                    painter->drawText(0, tempH + 1, w, fontH, Qt::AlignLeft, QString::number(i * _step + midValue, 'f', _decimals));
                }
                else
                {
                    painter->drawText(0, tempH - fontH - 1, w, fontH, Qt::AlignLeft, QString::number(i * _step + midValue, 'f', _decimals));
                }
            }
           

            int smallH = stepH / 10;
            double smallInterval = stepH / smallH;
            for(int j = 0; j < smallH; j++)
            {
                painter->drawLine(0.5 * w - 2, tempH - ( j + 1 ) * smallInterval, 0.5 * w + 2, tempH - ( j + 1 ) * smallInterval);
            }
        }
    }
    else if (_mode == DiffAxis::horiztal)
    {
        painter->drawLine(0, 0.5 * h, w, 0.5 * h);
       
        double stepW =  w  / interval;

        for(int i = -interval; i < interval; i++)
        {
            double tempW = w / 2 + i * stepW;

            //if (tempW >= 0 && tempW < w)
            {
                painter->drawLine(tempW, 0.5 * h - 7, tempW, 0.5 * h + 7);
                QString showNum = QString::number(i * _step + midValue, 'f', _decimals);

                if(tempW  <= w && tempW + 3 +  painter->fontMetrics().width(showNum) >= w)
                {
                    painter->drawText(tempW - 3 - painter->fontMetrics().width(showNum), h - fontH - 1, painter->fontMetrics().width(showNum), fontH, Qt::AlignLeft, showNum);
                }
                else
                {
                    painter->drawText(tempW + 3, h - fontH - 1, painter->fontMetrics().width(showNum), fontH, Qt::AlignLeft, showNum);
                }
            }
           
            int smallW = stepW / 10;
            double smallInterval = stepW / smallW;
            for(int j = 0; j < smallW; j++)
            {
                painter->drawLine(tempW + ( j + 1 ) * smallInterval, 0.5 * h - 2, tempW + ( j + 1 ) * smallInterval, 0.5 * h + 2);
            }
        }
        
    }

    painter->restore();
}

DiffAxis::DiffAxis(QWidget *parent) : QWidget(parent), impl(new DiffAxisImpl)
{
    impl->_mode = DiffAxis::vertical;
    impl->_type = DiffAxis::rangeType;
    impl->_step = 10;
    impl->_start = 0;
    impl->_end = 100;
    impl->_decimals = 0;
}

DiffAxis::~DiffAxis()
{
    delete impl;
    impl = nullptr;
}

DiffAxis::Mode DiffAxis::mode() const
{
    return impl->_mode;
}

void DiffAxis::setMode(Mode mode)
{
    if (impl->_mode != mode)
    {
        QRect geom = geometry();
        setGeometry(geom.x(), geom.y(), geom.height(), geom.width());
        impl->_mode = mode;
    }
}

DiffAxis::Type DiffAxis::type() const
{
    return impl->_type;
}

void DiffAxis::setType(DiffAxis::Type type)
{
    impl->_type = type;
}

double DiffAxis::step() const
{
    return impl->_step;
}

void DiffAxis::setStep(double step)
{
    impl->_step = step;
}

int DiffAxis::decimals() const
{
    return impl->_decimals;
}

void DiffAxis::setDecimals(int decimals)
{
    impl->_decimals = decimals;
}

double DiffAxis::start() const
{
    return impl->_start;
}

void DiffAxis::setStart(double start)
{
    impl->_start = start;
}

double DiffAxis::end() const
{
    return impl->_end;
}

void DiffAxis::setEnd(double end)
{
    impl->_end = end;
}

QSize DiffAxis::sizeHint() const
{
    if (impl->_mode == DiffAxis::vertical)
    {
        return QSize(32, 400);
    }
    else
    {
        return QSize(400, 32);
    }
}

QSize DiffAxis::minimumSizeHint() const
{
    if (impl->_mode == DiffAxis::vertical)
    {
        return QSize(32, 400);
    }
    else
    {
        return QSize(400, 32);
    }
}

void DiffAxis::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    impl->drawDiffAxis(&painter, width(), height());
}

void DiffAxis::setDescriptions(const QList<QString>& descriptions)
{
    impl->_descriptions = descriptions;
}

void DiffAxis::addDescription(const QString& description)
{
    impl->_descriptions.push_back(description);
}

} }
